查看原文
其他

bash 网络接口

2016-08-18 王聪 Linux内核之旅

我很早以前就见过 /dev/tcp/<host>/<port> 这个接口,但一直以为是某个 BSD 内核实现了一个特殊的文件系统,因为 Linux 上面很明显没有 /dev/tcp 这个目录。直到今天我才发现,这个目录其实是 bash 自己实现的。这么以来就可以不借助wget,nc 来实现网络连接了,设计这么一个接口是要逆天了吗?

使用这个接口很简单,如下所示:


bash-4.2$ cat </dev/tcp/time.nist.gov/13

56188 12-09-18 15:34:26 50 0 0 733.5 UTC(NIST) *

bash-4.2$ exec 3<>/dev/tcp/www.w3.org/80
bash-4.2$ echo -e “GET / HTTP/1.0nn” >&3
bash-4.2$ cat <&3
HTTP/1.1 200 OK
Date: Tue, 18 Sep 2012 15:41:08 GMT
Server: Apache/2
Content-Location: Home.html
Vary: negotiate,accept
TCN: choice
Last-Modified: Tue, 18 Sep 2012 14:06:27 GMT
ETag: “8f75-4c9fa65657ec0;89-3f26bd17a2f00”
Accept-Ranges: bytes
Content-Length: 36725
Cache-Control: max-age=600
Expires: Tue, 18 Sep 2012 15:51:08 GMT
P3P: policyref=”

Connection: close
Content-Type: text/html; charset=utf-8

在 bash 的源代码树 redir.c 文件中,我们不难发现下面的代码:

[c]
/ A list of pattern/value pairs for filenames that the redirection
code handles specially. 
/
static STRING_INT_ALIST _redir_special_filenames[] = {

if !defined (HAVE_DEV_FD)

{ “/dev/fd/[0-9]*”, RF_DEVFD },

endif

if !defined (HAVE_DEV_STDIN)

{ “/dev/stderr”, RF_DEVSTDERR },
{ “/dev/stdin”, RF_DEVSTDIN },
{ “/dev/stdout”, RF_DEVSTDOUT },

endif

if defined (NETWORK_REDIRECTIONS)

{ “/dev/tcp//“, RF_DEVTCP },
{ “/dev/udp//“, RF_DEVUDP },

endif

{ (char *)NULL, -1 }
};


static int
redir_open (filename, flags, mode, ri)
char *filename;
int flags, mode;
enum r_instruction ri;
{
int fd, r;

r = find_string_in_alist (filename, _redir_special_filenames, 1);
if (r >= 0)
return (redir_special_open (r, filename, flags, mode, ri));

/ If we are in noclobber mode, you are not allowed to overwrite
existing files. Check before opening. 
/
if (noclobber && CLOBBERING_REDIRECT (ri))
{
fd = noclobber_open (filename, flags, mode, ri);
if (fd == NOCLOBBER_REDIRECT)
return (NOCLOBBER_REDIRECT);
}
else
{
fd = open (filename, flags, mode);

if defined (AFS)

 if ((fd &lt; 0) &amp;&amp; (errno == EACCES))    {      fd = open (filename, flags &amp; ~O_CREAT, mode);      errno = EACCES;       /* restore errno */    }

endif / AFS /

}

return fd;
}

[/c]

可见,当 bash 发现重定向时它会先查看重定向的文件是不是特殊文件,如果是截获它,自行解释之,否则就打开这个文件。当然了,真正解释 /dev/tcp/HOST/PORT 的代码是在 lib/sh/netopen.c 中。

bash 的手册中也提到了这些特殊接口:

/dev/fd/fd
If fd is a valid integer, file descriptor fd is duplicated.
/dev/stdin
File descriptor 0 is duplicated.
/dev/stdout
File descriptor 1 is duplicated.
/dev/stderr
File descriptor 2 is duplicated.
/dev/tcp/host/port
If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts
to open a TCP connection to the corresponding socket.
/dev/udp/host/port
If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts
to open a UDP connection to the corresponding socket.


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存